home *** CD-ROM | disk | FTP | other *** search
/ Maclife 157 / MACLIFE157-2001-09.ISO.7z / MACLIFE157-2001-09.ISO / Linux / MacOS Tools / BootX 1.2.2 / Sources / lib / MoreInterfaceLib / MoreInterfaceLib.c next >
Text File  |  2001-07-23  |  19KB  |  501 lines

  1. /*
  2.     File:        MoreInterfaceLib.c
  3.  
  4.     Contains:    Compatibility shim for routines not in InterfaceLib prior to Mac OS 8.5.
  5.  
  6.     Written by:    Quinn
  7.  
  8.     Copyright:    Copyright ゥ 1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.  
  20.          <4>     20/4/99    Quinn   Added Gestalt Value routines.
  21.          <3>     16/3/99    Quinn   Added MoreUTFindDrive and MoreAddDrive.  Also fixed some mixups
  22.                                     about which traps are toolbox traps and which aren't.
  23.          <2>      1/3/99    Quinn   Added MoreFlushCodeCacheRange.  Also some general tidy up.
  24.          <1>     25/2/99    Quinn   First checked in.
  25. */
  26.  
  27. /////////////////////////////////////////////////////////////////
  28. // MoreIsBetter Setup
  29.  
  30. #include "MoreSetup.h"
  31.  
  32. /////////////////////////////////////////////////////////////////
  33. // Mac OS Interfaces
  34.  
  35. #include <CodeFragments.h>
  36. #include <LowMem.h>
  37. #include <Traps.h>
  38. #include <FSM.h>
  39. #include <Gestalt.h>
  40.  
  41. /////////////////////////////////////////////////////////////////
  42. // Our Prototypes
  43.  
  44. #include "MoreInterfaceLib.h"
  45.  
  46. /////////////////////////////////////////////////////////////////
  47.  
  48. // This file contains implementations of various Mac OS API routines
  49. // that were rolled in to InterfaceLib as of Mac OS 8.5.  They are
  50. // in the InterfaceLib stub library as of Universal Interfaces 3.2.
  51. // This code does the magic to decide whether the routine is available
  52. // via InterfaceLib, or whether we have to synthesise our own MixedMode
  53. // glue (or, in some cases, implementation).
  54.  
  55. // If you use any of the routines in this library, you must either:
  56. //
  57. // a) continue to hard link to InterfaceLib, in which case you won't
  58. //    launch on pre-8.5 systems (with a cryptic error message), or
  59. // b) weak link to InterfaceLib, in which case you must check that you're
  60. //    on 8.5 or later before calling any of these routine lest
  61. //    you die by trying to call nil.
  62.  
  63. // You can change the definition of the following compiler variable,
  64. // which causes these routine to always use the InterfaceLib variant.
  65. // You'd better make sure they're available, as described above.
  66.  
  67. #ifndef MORE_MAC_OS_8_5_OR_LATER
  68.     #define MORE_MAC_OS_8_5_OR_LATER 0
  69. #endif
  70.  
  71. // Also, Universal Interfaces 3.2 defines macros for some missing
  72. // low memory accessors.  For CFM code, these macros override
  73. // the external procedure definition.  So you can no longer
  74. // call the real accessors, even if you do depend on Mac OS 8.5
  75. // or greater.  This hack fixes the problem.  [Radar ID 2308604]
  76.  
  77. #undef LMGetUnitTableEntryCount
  78. #undef LMSetUnitTableEntryCount
  79.  
  80. /////////////////////////////////////////////////////////////////
  81.  
  82. #if TARGET_RT_MAC_CFM
  83.  
  84. extern pascal SInt16 MoreLMGetUnitTableEntryCount(void)
  85. {
  86.     if (MORE_MAC_OS_8_5_OR_LATER || (LMGetUnitTableEntryCount != (void *) kUnresolvedCFragSymbolAddress)) {
  87.         return LMGetUnitTableEntryCount();
  88.     } else {
  89.         return *((SInt16 *) 0x01d2);
  90.     }
  91. }
  92.  
  93. extern pascal void   MoreLMSetUnitTableEntryCount(SInt16 value)
  94. {
  95.     if (MORE_MAC_OS_8_5_OR_LATER || (LMSetUnitTableEntryCount != (void *) kUnresolvedCFragSymbolAddress)) {
  96.         LMSetUnitTableEntryCount(value);
  97.     } else {
  98.         *((SInt16 *) 0x01d2) = value;
  99.     }
  100. }
  101.  
  102. #endif
  103.  
  104. /////////////////////////////////////////////////////////////////
  105. // Mixed Mode ProcInfo Helper
  106.  
  107. // Bit Numbers
  108. //
  109. //  3         2         1         0
  110. // 10987654321098765432109876543210
  111.  
  112. // Stack Based Layout
  113. //
  114. //                             cccc <- calling convention = kPascalStackBased (0), kCStackBased (1), kThinkCStackBased (5)
  115. //                           ss     <- result size
  116. //                         ss       <- stack parameter 1 size
  117. //                       ss         <- stack parameter 2 size
  118. //                     ss           <- stack parameter 3 size
  119. //                   ss             <- stack parameter 4 size
  120. //                 ss               <- stack parameter 5 size
  121. //               ss                 <- stack parameter 6 size
  122. //             ss                   <- stack parameter 7 size
  123. //           ss                     <- stack parameter 8 size
  124. //         ss                       <- stack parameter 9 size
  125. //       ss                         <- stack parameter 10 size
  126. //     ss                           <- stack parameter 11 size
  127. //   ss                             <- stack parameter 12 size
  128.  
  129. // Register Based Layout
  130. //
  131. //                             cccc <- calling convention = kRegisterBased (2)
  132. //                      rrrss       <- register result location and size
  133. //                 rrrss            <- register parameter 1 location and size
  134. //            rrrss                 <- register parameter 1 location and size
  135. //       rrrss                      <- register parameter 1 location and size
  136. //  rrrss                           <- register parameter 1 location and size
  137.  
  138. // Dispatched Stack Based Layout
  139. //
  140. //                             cccc <- calling convention = kD0DispatchedPascalStackBased (8), kD1DispatchedPascalStackBased (12), kD0DispatchedCStackBased (9), kStackDispatchedPascalStackBased (14)
  141. //                           ss     <- result size
  142. //                         ss       <- selector size
  143. //                       ss         <- stack parameter 1 size
  144. //                     ss           <- stack parameter 2 size
  145. //                   ss             <- stack parameter 3 size
  146. //                 ss               <- stack parameter 4 size
  147. //               ss                 <- stack parameter 5 size
  148. //             ss                   <- stack parameter 6 size
  149. //           ss                     <- stack parameter 7 size
  150. //         ss                       <- stack parameter 8 size
  151. //       ss                         <- stack parameter 9 size
  152. //     ss                           <- stack parameter 10 size
  153. //   ss                             <- stack parameter 11 size
  154.  
  155. // Special Case Layout
  156. //
  157. //                             cccc <- calling convention = kSpecialCase (15)
  158. //                       xxxxxx     <- special case selector (see "MixedMode.h")
  159.  
  160. // Values for "ss":
  161. //
  162. // 00 = kNoByteCode
  163. // 01 = kOneByteCode
  164. // 10 = kTwoByteCode
  165. // 11 = kFourByteCode
  166.  
  167. // Values for "rrr":
  168. //
  169. //
  170. // 000 = kRegisterD0
  171. // 001 = kRegisterD1
  172. // 010 = kRegisterD2
  173. // 011 = kRegisterD3
  174. // 100 = kRegisterA0
  175. // 101 = kRegisterA1
  176. // 110 = kRegisterA2
  177. // 111 = kRegisterA3
  178.  
  179. /////////////////////////////////////////////////////////////////
  180.  
  181. #if TARGET_RT_MAC_CFM
  182.  
  183. // DriverInstallReserveMem is a bit trickier to implement than the
  184. // previous two routines.  Basically we have get the address of the
  185. // _DriverInstall ($A03D) trap and then call it using
  186. // CallOSTrapUniversalProc.  There are a number of important things
  187. // to note here:
  188. //   a) We can just get the trap address and treat it as a UPP.
  189. //      The trap tables are defined to contain UPPs, either pointers
  190. //      to real 68K code, or pointers to a routine descriptor (if
  191. //      the trap is native or fat).
  192. //   b) We must use CallOSTrapUniversalProc, not CallUniversalProc.
  193. //      CallOSTrapUniversalProc automatically does a number of things 
  194. //      that are very critical for call OS traps.  See "IM:PowerPC
  195. //      System Software", p2-42 for a full description.
  196. //   c) When calling OS traps from PPC, it's important to get the
  197. //      ProcInfo right.  Specifically, all OS traps assume an
  198. //      implicit parameter of D1 as the first parameter.  After
  199. //      that, the parameters should be defined in the order that
  200. //      they are declared in the prototype.  If you fail to get
  201. //      the order right, or to put D1 first, your code will work,
  202. //      up until it encounters someone who has patched the OS trap
  203. //      with a native or fat patch.  Then strange things will happen,
  204. //      and you'll spend hours in MacsBug trying to figure it out.
  205.  
  206. // The trap number and ProcInfo description for DriverInstallReserveMem.
  207.  
  208. enum {
  209.     _DriverInstallReserveMem = 0x0A43D
  210. };
  211.  
  212. enum {
  213.     uppDriverInstallProcInfo = kRegisterBased
  214.         | REGISTER_RESULT_LOCATION(kRegisterD0)
  215.         | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
  216.         | REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(long)))
  217.         | REGISTER_ROUTINE_PARAMETER(2, kRegisterA0, SIZE_CODE(sizeof(DRVRHeaderPtr)))
  218.         | REGISTER_ROUTINE_PARAMETER(3, kRegisterD0, SIZE_CODE(sizeof(short)))
  219. };
  220.  
  221. // IMPORTANT: Previous versions of TradDriverLoaderLib defined parameter 1
  222. // as sizeof(short), not sizeof(long).  I fixed this based on information
  223. // I extracted from the official Apple version of this glue, in the 
  224. // InterfaceLib implementation on Mac OS 8.5.
  225.  
  226. extern pascal OSErr  MoreDriverInstallReserveMem(DRVRHeaderPtr drvrPtr, DriverRefNum refNum)
  227. {
  228.     if (MORE_MAC_OS_8_5_OR_LATER || (DriverInstallReserveMem != (void *) kUnresolvedCFragSymbolAddress)) {
  229.         return DriverInstallReserveMem(drvrPtr, refNum);
  230.     } else {
  231.         UniversalProcPtr trapAddress;
  232.         
  233.         // Check that I've got the ProcInfo correct.  This magic value
  234.         // was extracted from InterfaceLib on Mac OS 8.5.
  235.  
  236.         MoreAssert(uppDriverInstallProcInfo == 0x00533822);
  237.         
  238.         trapAddress = GetOSTrapAddress(_DriverInstallReserveMem);
  239.         return CallOSTrapUniversalProc(trapAddress, uppDriverInstallProcInfo, _DriverInstallReserveMem, drvrPtr, refNum);
  240.     }
  241. }
  242.  
  243. #endif
  244.  
  245. /////////////////////////////////////////////////////////////////
  246.  
  247. #if TARGET_RT_MAC_CFM
  248.  
  249. enum {
  250.     uppFlushCodeCacheRangeProcInfo = kRegisterBased |
  251.             RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
  252.             REGISTER_RESULT_LOCATION(kRegisterD0) |
  253.             REGISTER_ROUTINE_PARAMETER(1, kRegisterD0, SIZE_CODE(sizeof(long))) |
  254.             REGISTER_ROUTINE_PARAMETER(2, kRegisterD1, SIZE_CODE(sizeof(long))) |
  255.             REGISTER_ROUTINE_PARAMETER(3, kRegisterA0, SIZE_CODE(sizeof(void *))) |
  256.             REGISTER_ROUTINE_PARAMETER(4, kRegisterA1, SIZE_CODE(sizeof(unsigned long)))
  257. };
  258.  
  259. extern pascal OSErr  MoreFlushCodeCacheRange(void *address, unsigned long count)
  260. {
  261.     if (MORE_MAC_OS_8_5_OR_LATER || (FlushCodeCacheRange != (void *) kUnresolvedCFragSymbolAddress)) {
  262.         return FlushCodeCacheRange(address, count);
  263.     } else {
  264.         UniversalProcPtr trapAddress;
  265.         
  266.         // Check that I've got the ProcInfo correct.  This magic value
  267.         // was extracted from InterfaceLib on Mac OS 8.5.
  268.  
  269.         MoreAssert(uppFlushCodeCacheRangeProcInfo == 0x5e671822);
  270.         
  271.         trapAddress = GetOSTrapAddress(_HWPriv);
  272.         return CallOSTrapUniversalProc(trapAddress, uppFlushCodeCacheRangeProcInfo, 9, _HWPriv, address, count);
  273.     }
  274. }
  275.  
  276. #endif
  277.  
  278. /////////////////////////////////////////////////////////////////
  279.  
  280. #if TARGET_RT_MAC_CFM
  281.  
  282. enum {
  283.     uppUTFindDriveProcInfo = kD0DispatchedPascalStackBased |
  284.             RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
  285.             DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(long))) |
  286.             DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(SInt16))) |
  287.             DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(DrvQElPtr *)))
  288. };
  289.  
  290. extern pascal OSErr MoreUTFindDrive(SInt16 driveNum, DrvQElPtr *driveQElementPtr)
  291. {
  292.     if (MORE_MAC_OS_8_5_OR_LATER || (UTFindDrive != (void *) kUnresolvedCFragSymbolAddress)) {
  293.         return UTFindDrive(driveNum, driveQElementPtr);
  294.     } else {
  295.         UniversalProcPtr trapAddress;
  296.         
  297.         // Check that I've got the ProcInfo correct.  This magic value
  298.         // was extracted from InterfaceLib on Mac OS 8.5.
  299.  
  300.         MoreAssert(uppUTFindDriveProcInfo == 0x0EE8);
  301.         
  302.         trapAddress = GetToolboxTrapAddress(_HFSUtilDispatch);
  303.         return CallUniversalProc(trapAddress, uppUTFindDriveProcInfo, 15, driveNum, driveQElementPtr);
  304.     }
  305. }
  306.  
  307. #endif
  308.  
  309. /////////////////////////////////////////////////////////////////
  310.  
  311. #if TARGET_RT_MAC_CFM
  312.  
  313. enum {
  314.     uppAddDriveProcInfo = kRegisterBased |
  315.             RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
  316.             REGISTER_RESULT_LOCATION(kRegisterD0) |
  317.             REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(short))) |
  318.             REGISTER_ROUTINE_PARAMETER(2, kRegisterA0, SIZE_CODE(sizeof(DrvQElPtr))) |
  319.             REGISTER_ROUTINE_PARAMETER(3, kRegisterD0, SIZE_CODE(sizeof(long)))
  320. };
  321.  
  322. // Some comments about the ProcInfo value:
  323. //
  324. // o It's set to return a result even though the high-level glue doesn't.
  325. //   This is because the trap returns a result in D0.  We can safely ignored
  326. //   it from the C code.
  327. //
  328. // o The D1 parameter is listed as sizeof(short), not sizeof(long) which is
  329. //   the size used by most other OS traps.  The reason: I'm not sure.
  330. //   Come to think of it, sizeof(short) makes more sense to me because
  331. //   that's what trap words are.  Anyway, I'm just parroting what
  332. //   InterfaceLib 8.5 does; my specific goal is to make CFM patches to
  333. //   AddDrive work properly, which requires that we all use identical
  334. //   ProcInfo's.
  335. //
  336. // o Register D0 contains the drvrRefNum and drvNum parameters combined,
  337. //   with drvNum in the high word and drvrRefNum in the low word.
  338. //   Oh, those wacky 68K calling conventions (-:
  339.  
  340. extern pascal void MoreAddDrive(DriverRefNum drvrRefNum, SInt16 drvNum, DrvQElPtr qEl)
  341. {
  342.     UInt32 response;
  343.     
  344.     if ( MORE_MAC_OS_8_5_OR_LATER || ((Gestalt(gestaltSystemVersion, (SInt32 *) &response) == noErr) && (response >= 0x0850))) {
  345.         AddDrive(drvrRefNum, drvNum, qEl);
  346.     } else {
  347.         UniversalProcPtr trapAddress;
  348.  
  349.         // Prior to Mac OS 8.5, the InterfaceLib glue for AddDrive was
  350.         // messed up, so we have to roll our own.
  351.         
  352.         // Check that I've got the ProcInfo correct.  This magic value
  353.         // was extracted from InterfaceLib on Mac OS 8.5.
  354.  
  355.         MoreAssert(uppAddDriveProcInfo == 0x0733022);
  356.         
  357.         trapAddress = GetOSTrapAddress(_AddDrive);
  358.         (void) CallOSTrapUniversalProc(trapAddress, uppUTFindDriveProcInfo, _AddDrive, qEl, ( ((UInt32) drvNum) << 16) | (UInt16) drvrRefNum);
  359.     }
  360. }
  361.  
  362. #else
  363.  
  364. // Unlike most of these glue routines, the 68K version of AddDrive 
  365. // is implemented as link-in glue.  Thus there are no inlines in the
  366. // interface file.  We therefore have to implement this routine for
  367. // classic 68K, as a simple call through to the real routine.
  368.  
  369. extern pascal void MoreAddDrive(DriverRefNum drvrRefNum, SInt16 drvNum, DrvQElPtr qEl)
  370. {
  371.     AddDrive(drvrRefNum, drvNum, qEl);
  372. }
  373.  
  374. #endif
  375.  
  376. /////////////////////////////////////////////////////////////////
  377.  
  378. #if TARGET_RT_MAC_CFM
  379.  
  380. enum {
  381.     _GestaltValue = 0xABF1
  382. };
  383.  
  384. enum {
  385.     uppNewGestaltValueProcInfo = kD0DispatchedPascalStackBased |
  386.             RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
  387.             DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
  388.             DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(OSType))) |
  389.             DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long))),
  390.     uppReplaceGestaltValueProcInfo = kD0DispatchedPascalStackBased |
  391.             RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
  392.             DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
  393.             DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(OSType))) |
  394.             DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long))),
  395.     uppSetGestaltValueProcInfo = kD0DispatchedPascalStackBased |
  396.             RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
  397.             DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
  398.             DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(OSType))) |
  399.             DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long))),
  400.     uppDeleteGestaltValueProcInfo = kD0DispatchedPascalStackBased |
  401.             RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
  402.             DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
  403.             DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(OSType)))
  404. };
  405.  
  406. // The glue I use here is especially cheesy.  In general, I try
  407. // to avoid using the pre-processor for generating bogus C syntax,
  408. // ie I only use #if where I could syntactically use if().  However,
  409. // in this case I've been forced to break my own rules.  The problem
  410. // is that NewGestaltValue etc are not present in Universal Interface's
  411. // 3.2 InterfaceLib for CFM-68K.  Why?  I don't know for sure, but it
  412. // could be because they are only available in the real InterfaceLib for
  413. // Mac OS 8.5 and higher, and that can't be run on 68K machines.  Anyway,
  414. // given that they're not available in InterfaceLib, you can't reference
  415. // the symbol in the CFM-68K build, which requires ugly preprocessor
  416. // stuff.  There may be a better way of doing this, but I'm pushed for
  417. // time right now.  I hope to revisit it eventually.
  418. // -- Quinn, 20 Apr 1999
  419.  
  420. extern pascal OSErr MoreNewGestaltValue(OSType selector, long newValue)
  421. {
  422.     #if !TARGET_CPU_68K
  423.         if (MORE_MAC_OS_8_5_OR_LATER || (NewGestaltValue != (void *) kUnresolvedCFragSymbolAddress)) {
  424.             return NewGestaltValue(selector, newValue);
  425.         } else
  426.     #endif
  427.         {
  428.             UniversalProcPtr trapAddress;
  429.             
  430.             // Check that I've got the ProcInfo correct.  This magic value
  431.             // was extracted from InterfaceLib on Mac OS 8.5.
  432.  
  433.             MoreAssert(uppNewGestaltValueProcInfo == 0x00000FA8);
  434.             
  435.             trapAddress = GetToolboxTrapAddress(_GestaltValue);
  436.             return CallUniversalProc(trapAddress, uppNewGestaltValueProcInfo, selector, newValue);
  437.         }
  438. }
  439.  
  440. extern pascal OSErr MoreReplaceGestaltValue(OSType selector, long replacementValue)
  441. {
  442.     #if !TARGET_CPU_68K
  443.         if (MORE_MAC_OS_8_5_OR_LATER || (ReplaceGestaltValue != (void *) kUnresolvedCFragSymbolAddress)) {
  444.             return ReplaceGestaltValue(selector, replacementValue);
  445.         } else
  446.     #endif
  447.         {
  448.             UniversalProcPtr trapAddress;
  449.             
  450.             // Check that I've got the ProcInfo correct.  This magic value
  451.             // was extracted from InterfaceLib on Mac OS 8.5.
  452.  
  453.             MoreAssert(uppReplaceGestaltValueProcInfo == 0x00000FA8);
  454.             
  455.             trapAddress = GetToolboxTrapAddress(_GestaltValue);
  456.             return CallUniversalProc(trapAddress, uppReplaceGestaltValueProcInfo, selector, replacementValue);
  457.         }
  458. }
  459.  
  460. extern pascal OSErr MoreSetGestaltValue(OSType selector, long newValue)        
  461. {
  462.     #if !TARGET_CPU_68K
  463.         if (MORE_MAC_OS_8_5_OR_LATER || (SetGestaltValue != (void *) kUnresolvedCFragSymbolAddress)) {
  464.             return SetGestaltValue(selector, newValue);
  465.         } else
  466.     #endif
  467.         {
  468.             UniversalProcPtr trapAddress;
  469.             
  470.             // Check that I've got the ProcInfo correct.  This magic value
  471.             // was extracted from InterfaceLib on Mac OS 8.5.
  472.  
  473.             MoreAssert(uppSetGestaltValueProcInfo == 0x00000FA8);
  474.             
  475.             trapAddress = GetToolboxTrapAddress(_GestaltValue);
  476.             return CallUniversalProc(trapAddress, uppSetGestaltValueProcInfo, selector, newValue);
  477.         }
  478. }
  479.  
  480. extern pascal OSErr MoreDeleteGestaltValue(OSType selector)
  481. {
  482.     #if !TARGET_CPU_68K
  483.         if (MORE_MAC_OS_8_5_OR_LATER || (DeleteGestaltValue != (void *) kUnresolvedCFragSymbolAddress)) {
  484.             return DeleteGestaltValue(selector);
  485.         } else
  486.     #endif
  487.         {
  488.             UniversalProcPtr trapAddress;
  489.             
  490.             // Check that I've got the ProcInfo correct.  This magic value
  491.             // was extracted from InterfaceLib on Mac OS 8.5.
  492.  
  493.             MoreAssert(uppDeleteGestaltValueProcInfo == 0x000003A8);
  494.             
  495.             trapAddress = GetToolboxTrapAddress(_GestaltValue);
  496.             return CallUniversalProc(trapAddress, uppDeleteGestaltValueProcInfo, selector);
  497.         }
  498. }
  499.  
  500. #endif
  501.